<template>
  <div class="coding-rule-page">
    <section class="coding-rule-main">
      <el-card class="form-card" shadow="hover">
        <template #header>
          <div class="card-header">
            <span>编辑编码规则</span>
            <span class="header-tip">{{ editingId ? '编辑中' : '新建规则' }}</span>
          </div>
        </template>
        <el-form
          ref="formRef"
          :model="ruleForm"
          :rules="formRules"
          label-width="110px"
          status-icon
        >
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="目标表单" prop="targettablename">
                <el-select v-model="ruleForm.targettablename" placeholder="请选择目标表单">
                  <el-option
                    v-for="item in targetOptions"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="编码名称" prop="rulename">
                <el-input v-model="ruleForm.rulename" placeholder="请输入编码名称" />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="编码前缀" prop="prefix">
                <el-input v-model="ruleForm.prefix" placeholder="例如：SCJH" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="时间规则" prop="timerule">
                <el-select
                  v-model="ruleForm.timerule"
                  placeholder="请选择时间格式"
                  clearable
                >
                  <el-option
                    v-for="item in timeRuleOptions"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>

          <el-form-item label="生成类型" prop="generatetype">
            <el-radio-group v-model="ruleForm.generatetype">
              <el-radio :label="1">每天</el-radio>
              <el-radio :label="2">递增</el-radio>
            </el-radio-group>
          </el-form-item>

          <el-row :gutter="20">
            <el-col :span="8">
              <el-form-item label="初始流水号" prop="initialserial">
                <el-input-number
                  v-model="ruleForm.initialserial"
                  :min="1"
                  :step="1"
                  controls-position="right"
                  @change="handleSerialChange"
                />
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="流水号长度" prop="seriallength">
                <el-input-number
                  v-model="ruleForm.seriallength"
                  :min="1"
                  :max="12"
                  :step="1"
                  controls-position="right"
                  @change="handleSerialChange"
                />
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="步长" prop="step">
                <el-input-number
                  v-model="ruleForm.step"
                  :min="1"
                  :max="999"
                  :step="1"
                  controls-position="right"
                />
              </el-form-item>
            </el-col>
          </el-row>

          <el-form-item label="编码生成规则">
            <el-input v-model="ruleForm.generatepattern" readonly />
          </el-form-item>

          <el-form-item label="编码预览">
            <el-input v-model="ruleForm.preview" placeholder="系统自动生成" readonly />
          </el-form-item>

          <div class="form-actions">
            <el-button type="primary" :loading="submitting" @click="handleSubmit">保存规则</el-button>
            <el-button @click="handleReset">重置</el-button>
            <el-button
              type="success"
              :disabled="!editingId"
              :loading="generating"
              @click="handleGenerateCode"
            >
              生成新编码
            </el-button>
          </div>
        </el-form>
      </el-card>

      <el-card class="list-card" shadow="hover">
        <template #header>
          <div class="card-header">
            <span>已配置的编码规则</span>
            <el-button type="primary" link @click="fetchRules">
              刷新
            </el-button>
          </div>
        </template>
        <el-empty v-if="ruleList.length === 0" description="暂无编码规则" />
        <el-table v-else :data="ruleList" border>
          <el-table-column prop="rulename" label="编码名称" min-width="140" />
          <el-table-column prop="targettablename" label="目标表单" min-width="120" />
          <el-table-column prop="generatepattern" label="编码生成规则" min-width="180" />
          <el-table-column prop="samplecode" label="最新预览" min-width="160" />
          <el-table-column label="操作" width="180" fixed="right">
            <template #default="{ row }">
              <el-button type="primary" size="small" link @click="handleEdit(row)">
                编辑
              </el-button>
              <el-button type="success" size="small" link @click="handleGenerateCode(row)">
                生成
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-card>
    </section>

   
  </div>
</template>

<script setup lang="ts">
import { reactive, ref, watch, onMounted, nextTick } from 'vue'
import https from '@/Http/http'
import { ElMessage, ElMessageBox, type FormRules } from 'element-plus'
import type { FormInstance } from 'element-plus'

interface CodingRule {
  id?: number
  targettablename: string
  rulename: string
  prefix: string
  timerule: string | null
  generatetype: number
  initialserial: number
  seriallength: number
  step: number
  generatepattern: string
  samplecode?: string
  preview?: string
}

const formRef = ref<FormInstance>()

const targetOptions = [
  { label: '生产计划', value: '生产计划' },
  { label: '工单', value: '工单' },
  { label: '物料', value: '物料' }
]

const timeRuleOptions = [
  { label: 'yyyy（年）', value: 'yyyy' },
  { label: 'yyyyMM（年月）', value: 'yyyyMM' },
  { label: 'yyyyMMdd（年月日）', value: 'yyyyMMdd' },
  { label: 'yyyyMMddHHmmss（年月日时分秒）', value: 'yyyyMMddHHmmss' }
]

const defaultTargetValue = targetOptions[0]?.value ?? ''

const ruleForm = reactive<CodingRule>({
  targettablename: defaultTargetValue,
  rulename: '',
  prefix: '',
  timerule: 'yyyyMMdd',
  generatetype: 1,
  initialserial: 1,
  seriallength: 6,
  step: 1,
  generatepattern: '',
  preview: ''
})

const formRules = reactive({
  targettablename: [{ required: true, message: '请选择目标表单', trigger: 'change' }],
  rulename: [{ required: true, message: '请输入编码名称', trigger: 'blur' }],
  prefix: [{ required: true, message: '请输入编码前缀', trigger: 'blur' }],
  seriallength: [{ required: true, message: '请输入流水号长度', trigger: 'change' }],
  initialserial: [{ required: true, message: '请输入初始流水号', trigger: 'change' }]
})

const ruleList = ref<CodingRule[]>([])
const guideTable = [
  { name: '目标表单', desc: '不可修改，不可编辑，用于区分编码的应用场景。' },
  { name: '编码名称', desc: '编码规则名称，唯一标识该规则。' },
  { name: '编码前缀', desc: '字母或字符组成，通常用于区分业务类型。' },
  { name: '时间规则', desc: '可选时间格式，如“yyyy”“yyyyMMdd”“yyyyMMddHHmmss”等。' },
  { name: '生成类型', desc: '每天：每日重置流水号；递增：全局递增不重置。' },
  { name: '初始流水号', desc: '流水号起始值，默认为 1。' },
  { name: '流水号长度', desc: '仅包含流水号长度，例如 6 代表补零至 6 位。' },
  { name: '步长', desc: '流水号递增间隔，默认为 1。' },
  { name: '编码生成规则', desc: '展示编码组成方式，前缀 + 时间规则 + 流水号。' },
  { name: '编码预览', desc: '预览当前设置下生成的编码样式。' }
]

const submitting = ref(false)
const generating = ref(false)
const editingId = ref<number | null>(null)
const autoPreview = ref(true)


const formatDate = (date: Date, pattern?: string | null) => {
  if (!pattern) return ''
  const replacements: Record<string, string> = {
    yyyy: date.getFullYear().toString(),
    MM: String(date.getMonth() + 1).padStart(2, '0'),
    dd: String(date.getDate()).padStart(2, '0'),
    HH: String(date.getHours()).padStart(2, '0'),
    mm: String(date.getMinutes()).padStart(2, '0'),
    ss: String(date.getSeconds()).padStart(2, '0')
  }

  let result = pattern
  Object.entries(replacements).forEach(([key, value]) => {
    result = result.replace(key, value)
  })
  return result
}

const buildPattern = () => {
  const prefixPart = ruleForm.prefix ?? ''
  const timePart = ruleForm.timerule ? `[${ruleForm.timerule}]` : ''
  const serialPart = ''.padStart(Math.max(ruleForm.seriallength, 1), '0')
  ruleForm.generatepattern = `${prefixPart}${timePart}${serialPart}`
}

const buildPreview = () => {
  const now = new Date()
  const timePart = formatDate(now, ruleForm.timerule)
  const serial = String(Math.max(ruleForm.initialserial, 0)).padStart(
    Math.max(ruleForm.seriallength, 1),
    '0'
  )
  ruleForm.preview = `${ruleForm.prefix || ''}${timePart}${serial}`
}

const handleSerialChange = () => {
  if (ruleForm.seriallength < String(ruleForm.initialserial).length) {
    ElMessage.warning('流水号长度小于当前初始值位数，已自动调整')
    ruleForm.seriallength = String(ruleForm.initialserial).length
  }
}

watch(
  () => [ruleForm.prefix, ruleForm.timerule, ruleForm.seriallength, ruleForm.initialserial],
  () => {
    if (!autoPreview.value) {
      return
    }
    buildPattern()
    buildPreview()
  }
)

const getStatusCode = (payload: any) => payload?.code ?? payload?.Code
const getPayloadData = <T,>(payload: any): T => payload?.data ?? payload?.Data
const getPayloadMsg = (payload: any): string => payload?.msg ?? payload?.Msg ?? ''

const fetchRules = async () => {
  try {
    const { data } = await https.Reads.get(`/CodingRule`)
    if (getStatusCode(data) === 1) {
      ruleList.value = getPayloadData<CodingRule[]>(data) || []
    } else {
      ElMessage.error(getPayloadMsg(data) || '获取编码规则失败')
    }
  } catch (error) {
    ElMessage.error('无法获取编码规则列表，请检查服务是否可用')
  }
}

const handleSubmit = async () => {
  const currentForm = formRef.value
  if (!currentForm) return
  const valid = await currentForm.validate()
  if (!valid) return
  submitting.value = true
  try {
    const payload = {
      targettablename: ruleForm.targettablename,
      rulename: ruleForm.rulename,
      prefix: ruleForm.prefix,
      timerule: ruleForm.timerule,
      generatetype: ruleForm.generatetype,
      initialserial: ruleForm.initialserial,
      seriallength: ruleForm.seriallength,
      step: ruleForm.step,
      generatepattern: ruleForm.generatepattern,
      samplecode: ruleForm.preview
    }

    let data
    if (editingId.value) {
      const response = await https.Writes.put(`/CodingRule/${editingId.value}`, payload)
      data = response.data
    } else {
      const response = await https.Writes.post("/CodingRule", payload)
      data = response.data
    }
    if (getStatusCode(data) === 1) {
      ElMessage.success('保存成功')
      if (!editingId.value) {
        editingId.value = getPayloadData<number>(data)
      }
      await fetchRules()
    } else {
      ElMessage.error(getPayloadMsg(data) || '保存失败')
    }
  } catch (error) {
    ElMessage.error('保存失败，请稍后重试')
  } finally {
    submitting.value = false
  }
}

const handleGenerateCode = async (row?: CodingRule) => {
  const targetId = row?.id ?? editingId.value
  if (!targetId) {
    ElMessage.warning('请先保存编码规则')
    return
  }

  // 若从列表触发，需要确认
  if (row && row.id) {
    try {
      await ElMessageBox.confirm(
        `确定基于规则「${row.rulename}」生成新的编码吗？`,
        '提示',
        { type: 'warning' }
      )
    } catch {
      return
    }
  }

  generating.value = true
  try {
    const { data } = await https.Writes.post(`/CodingRule/${targetId}/generate`, {
      ispreview: false
    })
    if (getStatusCode(data) === 1) {
      const codeValue = getPayloadData<string>(data)
      ElMessage.success(`生成成功：${codeValue}`)
      ruleForm.preview = codeValue
      await fetchRules()
    } else {
      ElMessage.error(getPayloadMsg(data) || '生成失败')
    }
  } catch (error) {
    ElMessage.error('生成失败，请检查服务是否可用')
  } finally {
    generating.value = false
  }
}

const handleEdit = (row: CodingRule) => {
  autoPreview.value = false
  editingId.value = row.id || null
  ruleForm.targettablename = row.targettablename
  ruleForm.rulename = row.rulename
  ruleForm.prefix = row.prefix
  ruleForm.timerule = row.timerule || null
  ruleForm.generatetype = row.generatetype
  ruleForm.initialserial = row.initialserial
  ruleForm.seriallength = row.seriallength
  ruleForm.step = row.step
  ruleForm.generatepattern = row.generatepattern
  ruleForm.preview = row.samplecode || ''
  nextTick(() => {
    autoPreview.value = true
  })
}

const handleReset = () => {
  editingId.value = null
  autoPreview.value = true
  formRef.value?.resetFields()
  Object.assign(ruleForm, {
    targettablename: defaultTargetValue,
    rulename: '',
    prefix: '',
    timerule: 'yyyyMMdd',
    generatetype: 1,
    initialserial: 1,
    seriallength: 6,
    step: 1
  })
  buildPattern()
  buildPreview()
}

onMounted(() => {
  buildPattern()
  buildPreview()
  fetchRules()
})
</script>

<style scoped>
.coding-rule-page {
  display: flex;
  gap: 20px;
  padding: 20px;
  background: #f5f6f8;
  min-height: calc(100vh - 60px);
  box-sizing: border-box;
}

.coding-rule-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.coding-rule-aside {
  width: 360px;
}

.form-card,
.list-card,
.desc-card {
  width: 100%;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;
}

.header-tip {
  color: #909399;
  font-size: 13px;
}

.form-actions {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
  margin-top: 10px;
}

.desc-text {
  color: #606266;
  margin-bottom: 12px;
  line-height: 1.6;
}
</style>

